//
// Created by LiuYou on 2021/10/24.
//

#include <csignal>
#include <unistd.h>
#include <cstdlib>
#include <cstdio>
#include "AnyTimer.hpp"


class Timer {
public:
    Timer(int sec, void (* jobFunc)(void*), void* funcArgs) :
            sec( sec ), jobFunc( jobFunc ), funcArgs( funcArgs ), pos( -1 ) {}

    ~Timer() = default;

public:
    int sec;
    Func jobFunc;
    void* funcArgs;
    int pos;

};


static Timer* jobArray[JOB_MAX];

static bool isInited = false;

static sighandler_t alarmHandlerSave;


static int getFreePos() {
    for (int i = 0; i < JOB_MAX; ++i) {
        if (jobArray[i] == nullptr) {
            return i;
        }
    }
    return -1;
}


static void alarmHandler(int signal) {
    for (int i = 0; i < JOB_MAX; ++i) {
        if (jobArray[i] != nullptr) {
            --jobArray[i]->sec;
            if (jobArray[i]->sec == 0) {
                jobArray[i]->jobFunc( jobArray[i]->funcArgs );
            }
        }
    }

    alarm( 1 );
}


static void moduleUnload() {
    fprintf( stdout, "执行模块卸载函数。\n" );

    signal( SIGALRM, alarmHandlerSave );
    alarm( 0 );
    for (int i = 0; i < JOB_MAX; ++i) {
        delete jobArray[i];
    }
}


static void moduleLoad() {
    alarmHandlerSave = signal( SIGALRM, alarmHandler );
    alarm( 1 );
    atexit( moduleUnload );
}


/**
 * @brief
 * @param sec
 * @param jobFunc
 * @param args
 * @return
 * <p>         >=  0       成功, 返回任务ID。
 * <p>         ==  -1      失败, 参数非法。
 * <p>         ==  -2      失败, 不能在支持其它任务了, 达到了计时器支持任务的上限。
 * <p>         ==  -3      失败, malloc();调用失败。
 */
int addJob(int sec, Func jobFunc, void* args) {


    if (!isInited) {
//        signal( SIGALRM, alarmHandler );
//        alarm( 1 );
        moduleLoad();
        isInited = true;
    }


    int pos = getFreePos();
    if (pos < 0) {
        return -1;
    }

    Timer* ptrTimer = new Timer( sec, jobFunc, args );
    ptrTimer->pos = pos;
    jobArray[pos] = ptrTimer;
    return pos;
}

/**
 * @brief
 * @param jobId
 * @return
 * <p>      ==  0       成功, 指定任务成功取消。
 * <p>      ==  -1      失败, 传入参数非法。
 * <p>      ==  -2      失败, 指定任务已经完成。
 * <p>      ==  -3      失败, 指定任务重复取消。
 */
int cancelJob(int jobId) {

    return 0;
}

/**
 * @brief
 * @param jobId
 * @return
 * <p>      ==  0       成功, 指定任务成功释放。
 * <p>      ==  -1      失败, 传入参数非法。
 */
int waitJob(int jobId) {
    Timer* me = jobArray[jobId];
    jobArray[jobId] = nullptr;
    delete me;
    return 0;
}


/* ************************************************************ */


int pauseJob(int jobId) {
    return 0;
}

int resumeJob(int jobId) {
    return 0;
}
